<template>
  <base-container>
    <div class="dept">
      <div class="w-20% h-full col p4 rd-2 bg-[var(--bg)]">
        <el-input v-model="searchTree" placeholder="请输入组织名称" clearable>
          <template #prepend>
            <base-icon name="iconfont-general gen-sousuo" :size="14" color="var(--ct4)" />
          </template>
        </el-input>
        <el-tree
          class="dept-tree"
          ref="treeRef"
          :data="deptTreeData"
          node-key="id"
          default-expand-all
          highlight-current
          :expand-on-click-node="false"
          :current-node-key="searchParams.deptId"
          :filter-node-method="handleSearchTree"
          @node-click="handleClickTreeNode"
        >
          <template #default="{ data }">
            <div class="tree-custom-node">
              <span>{{ data.deptName }}</span>
              <div class="node-more" v-if="hasAuth([PERMS.DEPT.ADD, PERMS.DEPT.UPDATE, PERMS.DEPT.DELETE])">
                <el-dropdown placement="bottom-end" :persistent="false" @click.stop>
                  <base-icon class="node-more-icon" name="iconfont-general gen-gengduo" :size="16" color="var(--ct3)" />
                  <template #dropdown>
                    <el-dropdown-menu>
                      <el-dropdown-item v-if="hasAuth([PERMS.DEPT.ADD])" @click="handleOpenAddDept(data)">
                        新增下级
                      </el-dropdown-item>
                      <el-dropdown-item v-if="hasAuth([PERMS.DEPT.UPDATE])" @click="handleOpenRenameDept(data)">
                        重命名
                      </el-dropdown-item>
                      <el-dropdown-item
                        v-if="data.parentId !== 0 && hasAuth([PERMS.DEPT.DELETE])"
                        @click="loadDeleteDept(data.id)"
                      >
                        删除
                      </el-dropdown-item>
                    </el-dropdown-menu>
                  </template>
                </el-dropdown>
              </div>
            </div>
          </template>
        </el-tree>
      </div>
      <base-card class="flex-1 h-full" :header-style="{ padding: '21px 24px' }">
        <template #header>
          <div class="w-full nowrap between">
            <div class="nowrap">
              <span>{{ curDeptName }}</span>
              <div class="nowrap ml3">
                <span class="text-4 c-[var(--bd)] font-500 lh-5">{{ page.total || 0 }}</span>
                <span class="text-3.5 font-400 ml4px lh-5">个账号</span>
              </div>
            </div>
            <div class="w220px">
              <el-input
                v-model="searchParams.fuzzyMixed"
                placeholder="请输入姓名/账号"
                clearable
                @keyup.enter="loadGetTableData"
                @clear="loadGetTableData"
              >
                <template #prepend>
                  <base-icon name="iconfont-general gen-sousuo" :size="14" color="var(--ct4)" />
                </template>
              </el-input>
            </div>
          </div>
        </template>

        <div class="col">
          <el-tabs v-model="searchParams.status" @tab-change="loadGetTableData">
            <el-tab-pane label="正常" :name="1" />
            <el-tab-pane label="已停用" :name="0" />
          </el-tabs>
          <avue-crud
            ref="avueCrudRef"
            :option="tableOption"
            :data="tableData"
            v-model="formData"
            :page="page"
            :table-loading="tableLoading"
            @refresh-change="loadGetTableData"
            @current-change="loadTablePageChange"
            @size-change="loadTablePageSizeChange"
            @row-save="loadAdd"
            @row-update="loadEdit"
          >
            <template #roles="{ row }">
              <div class="nowrap cursor-pointer" v-if="row.roles && row.roles.length">
                <el-tag
                  v-for="role in row.roles.slice(0, 2)"
                  :key="role.id"
                  class="mr8px"
                  type="info"
                  disable-transitions
                >
                  {{ role.roleName }}
                </el-tag>
                <el-popover placement="top" :width="268" trigger="hover" v-if="row.roles.length > 2">
                  <template #reference>
                    <base-icon name="iconfont-general gen-gengduo" :size="20" color="var(--ct3)" />
                  </template>
                  <div class="flex-wrap">
                    <el-tag class="m1" v-for="item in row.roles" :key="item.id" type="info" disable-transitions>
                      {{ item.roleName }}
                    </el-tag>
                  </div>
                </el-popover>
              </div>
            </template>
            <template #menu="{ row }">
              <el-button type="primary" text v-auth="[PERMS.DEPT.CHANGE]" @click="handleOpenChangeDept(row)">
                更改组织
              </el-button>
              <el-button
                type="primary"
                text
                v-auth="[PERMS.USER.ENABLE]"
                :disabled="row.statusLoading || row.isAdmin === 1"
                @click="handleStatusChange(row)"
              >
                {{ row.status === 1 ? "停用" : "启用" }}
              </el-button>
              <el-button
                type="info"
                text
                v-auth="[PERMS.USER.DELETE]"
                :disabled="row.status === 1"
                @click="loadDel(row)"
              >
                删除
              </el-button>
            </template>
          </avue-crud>
        </div>
      </base-card>
    </div>
    <!-- 新增组织 -->
    <add-dept
      v-model="showAddDept"
      width="404px"
      title="新增组织"
      :dept-info="curDeptInfo"
      :close-on-click-modal="false"
      @success="loadDeptTree"
    />
    <!-- 重命名 -->
    <rename-dept
      v-model="showChangeDept"
      width="404px"
      title="重命名"
      :dept-info="curDeptInfo"
      :close-on-click-modal="false"
      @success="loadDeptTree"
    />
    <!-- 更改组织 -->
    <change-dept
      v-model="showRenameDept"
      width="404px"
      title="更改组织"
      :dept-list="deptTreeData"
      :user-info="curUserInfo"
      :close-on-click-modal="false"
      @success="loadGetTableData"
    />
  </base-container>
</template>

<script setup>
  import Option from "@/crudOption/setting/permission/dept";
  import AddDept from "../components/AddDept.vue";
  import RenameDept from "../components/RenameDept.vue";
  import ChangeDept from "../components/ChangeDept.vue";

  // 获取全局方法
  const App = useGlobals();

  onMounted(() => {
    // 获取部门树数据
    loadDeptTree();
  });

  // 部门搜索关键词
  const searchTree = ref("");

  // 树组件实例
  const treeRef = ref();

  // 当前选中部门名称
  const curDeptName = ref("");

  // 部门树数据
  const deptTreeData = ref();

  // 获取部门树数据
  const loadDeptTree = () => {
    Api.dept.GetDeptTree().then(res => {
      // 更新部门树数据
      deptTreeData.value = res.data || [];
      // 获取第一个节点的ID，作为默认选中节点
      if (deptTreeData.value.length > 0) {
        const firstNodeId = deptTreeData.value[0].id;
        const deptName = deptTreeData.value[0].deptName;
        // 设置默认选中部门名称
        curDeptName.value = deptName;
        // 设置默认选中部门ID
        searchParams.value.deptId = firstNodeId;
        // 重新加载表格数据
        loadGetTableData();
      }
    });
  };

  // 监听搜索框内容变化，进行树节点过滤
  watch(
    () => searchTree.value,
    val => treeRef.value.filter(val)
  );

  // 部门搜索函数
  const handleSearchTree = (value, data) => {
    if (!value) return true;
    return data.deptName.includes(value);
  };

  // 点击树节点
  const handleClickTreeNode = node => {
    // 避免重复点击同一节点时重复加载
    if (searchParams.value.deptId === node.id) return;
    // 设置选中部门名称
    curDeptName.value = node.deptName;
    // 设置选中部门ID
    searchParams.value.deptId = node.id;
    // 重新加载表格数据
    loadGetTableData();
  };

  // avue-crud 组件实例
  const avueCrudRef = ref({});

  // 增删改查 hook
  let {
    data: tableData,
    loading: tableLoading,
    page: page,
    search: searchParams,
    form: formData,
    get: loadGetTableData,
    add: loadAdd,
    edit: loadEdit,
    del: loadDel,
    pageNumChange: loadTablePageChange,
    pageSizeChange: loadTablePageSizeChange,
  } = useCrudHook({
    get: Api.user.GetUserPage,
    add: Api.user.AddUser,
    edit: Api.user.UpdateUser,
    del: Api.user.DeleteUser,
    search: { status: 1, fuzzyMixed: "" },
    delConfirm: {
      title: "提示",
      content: "确认删除该成员吗？",
      type: "warning",
    },
  });

  // 获取 表格配置
  const { tableOption } = Option(formData);

  // 用户状态启用/禁用切换
  const handleStatusChange = row => {
    App.$confirm(`是否${row.status === 1 ? "停用" : "启用"}该成员？`, "提示", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",
    }).then(() => {
      const status = row.status === 1 ? 0 : 1; // 先取反
      row.statusLoading = true;
      Api.user
        .ChangeUserStatus({ id: row.id, status: status })
        .then(() => {
          // 操作结果
          $msg.success(status ? "启用成功" : "停用成功");
          // 重新加载表格数据
          loadGetTableData();
        })
        .finally(() => {
          row.statusLoading = false;
        });
    });
  };

  // 监听权限变化，更新操作栏是否显示
  tableOption.value.menu = computed(() => hasAuth([PERMS.DEPT.CHANGE, PERMS.USER.UPDATE, PERMS.USER.DELETE]));

  // 监听菜单操作权限变化，更新操作菜单宽度
  tableOption.value.menuWidth = computed(() => {
    let width = 0;
    if (hasAuth(PERMS.DEPT.CHANGE)) width += 72; // 4个字按钮宽度 72px
    if (hasAuth(PERMS.USER.UPDATE)) width += 60; // 2个字按钮宽度 60px
    if (hasAuth(PERMS.USER.DELETE)) width += 60; // 2个字按钮宽度 60px
    return width;
  });

  // 弹窗显示状态
  const showAddDept = ref(false);
  const showChangeDept = ref(false);
  const showRenameDept = ref(false);

  // 当前操作的部门信息
  const curDeptInfo = ref(null);
  // 当前操作的成员信息
  const curUserInfo = ref(null);

  // 打开新增部门弹窗
  const handleOpenAddDept = row => {
    curDeptInfo.value = row || {};
    showAddDept.value = true;
  };

  // 打开重命名弹窗
  const handleOpenRenameDept = row => {
    curDeptInfo.value = row || {};
    showChangeDept.value = true;
  };

  // 打开更改组织弹窗
  const handleOpenChangeDept = row => {
    curUserInfo.value = row || {};
    showRenameDept.value = true;
  };

  // 删除部门
  const loadDeleteDept = id => {
    App.$confirm("确认删除该组织吗？", "提示", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",
    }).then(() => {
      Api.dept.DeleteDept({ id: id }).then(() => {
        $msg.success("删除成功");
        // 重新加载部门树
        loadDeptTree();
      });
    });
  };
</script>
<style lang="scss" scoped>
  .dept {
    width: 100%;
    height: 100%;
    display: flex;
    flex-wrap: nowrap;
    gap: 16px;

    // 搜索输入框样式
    :deep(.el-input__wrapper) {
      padding: 0 8px;
      border: 1px solid var(--el-border-color);
      border-left: 0px;
      box-shadow: none;
    }

    :deep(.el-input-group__prepend) {
      padding: 0 0 0 8px;
      background-color: var(--el-fill-color-blank);
    }

    // 树形控件样式
    .dept-tree {
      margin-top: 12px;

      // 选中时样式
      :deep(.el-tree-node.is-current > .el-tree-node__content) {
        font-weight: 500;
        border-radius: 8px;
        background: var(--bd9);

        .tree-custom-node .node-more {
          &:hover {
            background-color: transparent;
          }
        }
      }

      // hover 时样式
      :deep(.el-tree-node__content) {
        --el-tree-node-content-height: 36px;
        margin: 2px 0;

        &:hover {
          border-radius: 8px;
          background-color: var(--fl1);
        }

        .el-icon svg {
          display: none;
        }

        .el-icon {
          font-family: var(--iconfont-general-family) !important;
          font-size: 12px;
          font-style: normal;
          -webkit-font-smoothing: antialiased;
          -moz-osx-font-smoothing: grayscale;

          &::before {
            content: "\e62c";
            display: block;
          }
        }
      }

      // 自定义节点内容样式
      .tree-custom-node {
        width: 100%;
        display: flex;
        flex-wrap: nowrap;
        justify-content: space-between;
        align-items: center;
        overflow: hidden;

        > span {
          display: inline-block;
          margin-right: 12px;
          text-overflow: ellipsis;
          white-space: nowrap;
          overflow: hidden;
        }

        .node-more {
          flex-shrink: 0;
          width: 24px;
          height: 24px;
          display: flex;
          justify-content: center;
          align-items: center;
          margin-right: 8px;
          cursor: pointer;
          border-radius: 50%;

          .node-more-icon {
            display: none;
          }

          &:hover {
            border-radius: 50%;
            background-color: var(--fl2);
          }
        }

        &:hover {
          .node-more .node-more-icon {
            display: inline-block;
          }
        }
      }
    }
  }
</style>
